﻿namespace Hishop.Weixin.Pay
{
    using Hishop.Weixin.Pay.Domain;
    using Hishop.Weixin.Pay.Util;
    using Newtonsoft.Json;
    using System;

    public class PayClient
    {
        private PayAccount _payAccount;
        public static readonly string Deliver_Notify_Url = "https://api.weixin.qq.com/pay/delivernotify";

        public PayClient(PayAccount account) : this(account.AppId, account.AppSecret, account.PartnerId, account.PartnerKey, account.PaySignKey)
        {
        }

        public PayClient(string appId, string appSecret, string partnerId, string partnerKey, string paySignKey)
        {
            PayAccount account = new PayAccount {
                AppId = appId,
                AppSecret = appSecret,
                PartnerId = partnerId,
                PartnerKey = partnerKey,
                PaySignKey = paySignKey
            };
            this._payAccount = account;
        }

        internal string BuildPackage(PackageInfo package)
        {
            PayDictionary parameters = new PayDictionary();
            parameters.Add("attach", package.Attach);
            parameters.Add("bank_type", package.BankType);
            parameters.Add("body", package.Body);
            parameters.Add("fee_type", package.FeeType);
            parameters.Add("goods_tag", package.GoodsTag);
            parameters.Add("input_charset", package.InputCharset);
            parameters.Add("notify_url", package.NotifyUrl);
            parameters.Add("out_trade_no", package.OutTradeNo);
            parameters.Add("partner", this._payAccount.PartnerId);
            parameters.Add("product_fee", package.ProductFee);
            parameters.Add("spbill_create_ip", package.SpbillCreateIp);
            parameters.Add("time_start", package.TimeExpire);
            parameters.Add("time_expire", package.TimeStart);
            parameters.Add("total_fee", (int) package.TotalFee);
            parameters.Add("transport_fee", package.TransportFee);
            string str = SignHelper.SignPackage(parameters, this._payAccount.PartnerKey);
            string str2 = SignHelper.BuildQuery(parameters, true);
            return string.Format("{0}&sign={1}", str2, str);
        }

        public PayRequestInfo BuildPayRequest(PackageInfo package)
        {
            PayRequestInfo info = new PayRequestInfo {
                appId = this._payAccount.AppId,
                package = this.BuildPackage(package),
                timeStamp = Utils.GetCurrentTimeSeconds().ToString(),
                nonceStr = Utils.CreateNoncestr()
            };
            PayDictionary parameters = new PayDictionary();
            parameters.Add("appid", this._payAccount.AppId);
            parameters.Add("appkey", this._payAccount.PaySignKey);
            parameters.Add("package", info.package);
            parameters.Add("timestamp", info.timeStamp);
            parameters.Add("noncestr", info.nonceStr);
            info.paySign = SignHelper.SignPay(parameters);
            return info;
        }

        public bool DeliverNotify(DeliverInfo deliver)
        {
            string token = Utils.GetToken(this._payAccount.AppId, this._payAccount.AppSecret);
            return this.DeliverNotify(deliver, token);
        }

        public bool DeliverNotify(DeliverInfo deliver, string token)
        {
            PayDictionary parameters = new PayDictionary();
            parameters.Add("appkey", this._payAccount.PaySignKey);
            parameters.Add("appid", this._payAccount.AppId);
            parameters.Add("openid", deliver.OpenId);
            parameters.Add("transid", deliver.TransId);
            parameters.Add("out_trade_no", deliver.OutTradeNo);
            parameters.Add("deliver_timestamp", Utils.GetTimeSeconds(deliver.TimeStamp));
            parameters.Add("deliver_status", deliver.Status ? 1 : 0);
            parameters.Add("deliver_msg", deliver.Message);
            deliver.AppId = this._payAccount.AppId;
            deliver.AppSignature = SignHelper.SignPay(parameters);
            parameters.Remove("appkey");
            parameters.Add("app_signature", deliver.AppSignature);
            parameters.Add("sign_method", deliver.SignMethod);
            string data = JsonConvert.SerializeObject(parameters);
            string url = string.Format("{0}?access_token={1}", Deliver_Notify_Url, token);
            string str3 = new WebUtils().DoPost(url, data);
            if (!(!string.IsNullOrEmpty(str3) && str3.Contains("ok")))
            {
                return false;
            }
            return true;
        }
    }
}

